﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.IO;

using MEFedMVVM.ViewModelLocator;
using Cinch;
using System.Configuration;
using System.Data;

namespace Anata.Client
{

    /// <summary>
    /// Runtime implementation of the 
    /// Data service used by the <c>ImageLoaderViewModel</c> to obtain data
    /// </summary>
    [PartCreationPolicy(CreationPolicy.NonShared)]
    [ExportService(ServiceType.Runtime, typeof(ITransaksiProvider))]
    public class TransaksiProvider : ITransaksiProvider
    {
        #region Data
        /*
        private BackgroundTaskManager<int, List<Transaksi>> multiFetchBgWorker =
            new BackgroundTaskManager<int, List<Transaksi>>();
        private BackgroundTaskManager<int, Transaksi> singleFetchBgWorker =
            new BackgroundTaskManager<int, Transaksi>();
        private BackgroundTaskManager<Transaksi, Transaksi> singleUpdateBgWorker =
            new BackgroundTaskManager<Transaksi, Transaksi>();
        private BackgroundTaskManager<int, bool> processBgWorker =
            new BackgroundTaskManager<int, bool>();
        */

        private BackgroundTaskManager<int, List<TransaksiThumbnailViewModel>> multiFetchTVMBgWorker =
            new BackgroundTaskManager<int, List<TransaksiThumbnailViewModel>>();
        private BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel> singleUpdateTVMBgWorker =
            new BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel>();
        private BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel> singleUpdateVMBgWorker =
            new BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel>();
        #endregion

        #region PublicMethods
        /*
        public void LazyFetchTransaksis(int page, Action<List<Transaksi>> callback)
        {
            BackgroundTaskManager<int, List<Transaksi>> bgWorker = null;
            if (multiFetchBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<int, List<Transaksi>>();
            }
            else
            {
                bgWorker = multiFetchBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
                {
                    return FetchTransaksisInternal(argument);
                };

            bgWorker.CompletionAction = (result) =>
                {
                    callback(result);
                };

            bgWorker.WorkerArgument = page;
            bgWorker.RunBackgroundTask();

        }

        public void LazyFetchTransaksi(int idTransaksi, Action<Transaksi> callback)
        {
            BackgroundTaskManager<int, Transaksi> bgWorker = null;
            if (singleFetchBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<int, Transaksi>();
            }
            else
            {
                bgWorker = singleFetchBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return FetchTransaksiInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = idTransaksi;
            bgWorker.RunBackgroundTask();

        }

        public void LazyUpdateTransaksi(Transaksi pTransaksi, Action<Transaksi> callback)
        {
            BackgroundTaskManager<Transaksi, Transaksi> bgWorker = null;
            if (singleUpdateBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<Transaksi, Transaksi>();
            }
            else
            {
                bgWorker = singleUpdateBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return UpdateTransaksiInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = pTransaksi;
            bgWorker.RunBackgroundTask();

        }

        public void LazyPayTransaksi(Transaksi pTransaksi, Action<Transaksi> callback)
        {
            BackgroundTaskManager<Transaksi, Transaksi> bgWorker = null;
            if (singleUpdateBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<Transaksi, Transaksi>();
            }
            else
            {
                bgWorker = singleUpdateBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return PayTransaksiInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = pTransaksi;
            bgWorker.RunBackgroundTask();
        }

        public void LazyCancelTransaksi(int idTransaksi, Action<Transaksi> callback)
        {
            BackgroundTaskManager<int, Transaksi> bgWorker = null;
            if (singleFetchBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<int, Transaksi>();
            }
            else
            {
                bgWorker = singleFetchBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return CancelTransaksiInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = idTransaksi;
            bgWorker.RunBackgroundTask();
        }
        */
        
        public void LazyFetchTransaksis(int page, Action<List<TransaksiThumbnailViewModel>> callback) 
        {
            BackgroundTaskManager<int, List<TransaksiThumbnailViewModel>> bgWorker = null;
            if (multiFetchTVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<int, List<TransaksiThumbnailViewModel>>();
            }
            else
            {
                bgWorker = multiFetchTVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return FetchTransaksiTVMsInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = page;
            bgWorker.RunBackgroundTask();
        }
        public void LazyLoadTransaksi(TransaksiThumbnailViewModel ttvm, Action<TransaksiThumbnailViewModel> callback)
        {
            BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel> bgWorker = null;
            if (singleUpdateTVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel>();
            }
            else
            {
                bgWorker = singleUpdateTVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return LoadTransaksiTVMInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = ttvm;
            bgWorker.RunBackgroundTask();
        }
        public void LazySaveTransaksi(TransaksiThumbnailViewModel ttvm, Action<TransaksiThumbnailViewModel> callback)
        {
            BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel> bgWorker = null;
            if (singleUpdateTVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel>();
            }
            else
            {
                bgWorker = singleUpdateTVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return SaveTransaksiTVMInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = ttvm;
            bgWorker.RunBackgroundTask();
        }
        public void LazyLoadTransaksi(TransaksiViewModel tvm, Action<TransaksiViewModel> callback)
        {
            BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel> bgWorker = null;
            if (singleUpdateVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel>();
            }
            else
            {
                bgWorker = singleUpdateVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return LoadTransaksiVMInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = tvm;
            bgWorker.RunBackgroundTask();
        }
        public void LazySaveTransaksi(TransaksiViewModel tvm, Action<TransaksiViewModel> callback)
        {
            BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel> bgWorker = null;
            if (singleUpdateVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel>();
            }
            else
            {
                bgWorker = singleUpdateVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return SaveTransaksiVMInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = tvm;
            bgWorker.RunBackgroundTask();
        }
        public void LazyLoadPembayaran(TransaksiViewModel tvm, Action<TransaksiViewModel> callback)
        {
            BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel> bgWorker = null;
            if (singleUpdateVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel>();
            }
            else
            {
                bgWorker = singleUpdateVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return LoadPembayaranVMInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = tvm;
            bgWorker.RunBackgroundTask();
        }
        public void LazySavePembayaran(TransaksiViewModel tvm, Action<TransaksiViewModel> callback)
        {
            BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel> bgWorker = null;
            if (singleUpdateVMBgWorker.TaskFunc != null)
            {
                bgWorker = new BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel>();
            }
            else
            {
                bgWorker = singleUpdateVMBgWorker;
            }

            bgWorker.TaskFunc = (argument) =>
            {
                return SavePembayaranVMInternal(argument);
            };

            bgWorker.CompletionAction = (result) =>
            {
                callback(result);
            };

            bgWorker.WorkerArgument = tvm;
            bgWorker.RunBackgroundTask();
        }
        #endregion

        #region PublicProperties
        /// <summary>
        /// To allow this class to be unit tested stand alone
        /// See CinchV1 articles about Unit Testing for this
        /// Or comments in Cinch BackgroundTaskManager<T> class
        /// </summary>
        public BackgroundTaskManager<int, List<TransaksiThumbnailViewModel>> MultiFetchTVMBgWorker
        {
            get { return multiFetchTVMBgWorker; }
        }
        public BackgroundTaskManager<TransaksiThumbnailViewModel, TransaksiThumbnailViewModel> SingleUpdateTVMBgWorker
        {
            get { return singleUpdateTVMBgWorker; }
        }
        public BackgroundTaskManager<TransaksiViewModel, TransaksiViewModel> SingleUpdateVMBgWorker
        {
            get { return singleUpdateVMBgWorker; }
        }
        #endregion

        #region PrivateMethods
        /*
        private List<Transaksi> FetchTransaksisInternal(int page)
        {
            List<Transaksi> transaksis = new List<Transaksi>();
            try
            {
                int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
                using (AnataEntities context = new AnataEntities())
                {
                    IQueryable<Transaksi> query =
                        from transaksi in context.Transaksi
                            .Include("Konsumen")
                            .Include("TransaksiLayanan.Layanan")
                            .Include("TransaksiLayanan.Karyawan")
                            .Include("TransaksiLayanan.JenisStok")
                            .Include("TransaksiProduk.JenisStok")
                            .Include("TransaksiProduk.Karyawan")
                            .Include("TransaksiPembayaran.JenisPembayaran")
                        orderby transaksi.WaktuSelesai
                        select transaksi;
                    transaksis = query.ToList().Skip(page * pageSize).Take(pageSize).ToList();
                }
            }
            catch (Exception) {
                throw;
            }
            return transaksis;
        }

        private Transaksi FetchTransaksiInternal(int idTransaksi)
        {
            Transaksi retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    IQueryable<Transaksi> query =
                        from transaksi in context.Transaksi
                            .Include("Konsumen")
                            .Include("TransaksiLayanan.Layanan")
                            .Include("TransaksiLayanan.Karyawan")
                            .Include("TransaksiLayanan.JenisStok")
                            .Include("TransaksiProduk.JenisStok")
                            .Include("TransaksiProduk.Karyawan")
                            .Include("TransaksiPembayaran.JenisPembayaran")
                        where transaksi.IdTransaksi == idTransaksi
                        select transaksi;
                    retval = query.ToList().FirstOrDefault();
                }
            }
            catch (Exception) { }
            return retval;
        }

        private Transaksi UpdateTransaksiInternal(Transaksi pTransaksi)
        {
            Transaksi retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    retval = SynchTransaksi(pTransaksi, context);
                    context.SaveChanges();

                    IQueryable<Transaksi> query =
                        from transaksi in context.Transaksi
                            .Include("Konsumen")
                            .Include("TransaksiLayanan.Layanan")
                            .Include("TransaksiLayanan.Karyawan")
                            .Include("TransaksiLayanan.JenisStok")
                            .Include("TransaksiProduk.JenisStok")
                            .Include("TransaksiProduk.Karyawan")
                            .Include("TransaksiPembayaran.JenisPembayaran")
                        where transaksi.IdTransaksi == retval.IdTransaksi
                        select transaksi;
                    retval = query.ToList().FirstOrDefault();
                }
            }
            catch (Exception) { }
            return retval;
        }

        private Transaksi PayTransaksiInternal(Transaksi pTransaksi)
        {
            Transaksi retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    pTransaksi.WaktuSelesai = DateTime.Now;
                    SynchTransaksi(pTransaksi, context);
                    
                    
                    
                    //penambahan / pengurangan kas
                    Int64 totalPembayaran = 0;
                    Int64 totalPembayaranTunai = 0;
                    foreach (TransaksiPembayaran tp in pTransaksi.TransaksiPembayaran)
                    {
                        totalPembayaran += tp.NominalPembayaran;
                        if (tp.JenisPembayaran.IsTunai) {
                            totalPembayaranTunai += tp.NominalPembayaran;
                        }
                    }
                    MutasiKasCabang mutasiKas = context.MutasiKasCabang.CreateObject();
                    mutasiKas.IdCabang = pTransaksi.IdCabang;
                    mutasiKas.IsOtomatis = true;
                    mutasiKas.NominalMutasi = totalPembayaranTunai - (totalPembayaran - pTransaksi.TotalHarga);
                    //TODO: get current session user
                    //mutasi.IdUser = SessionController.CurrentUser.IdUser;
                    mutasiKas.LastUpdated = DateTime.Now;
                    context.MutasiKasCabang.AddObject(mutasiKas);

                    
                    
                    //Pengurangan Stok
                    MutasiStok mutasiStok = null;
                    Stok stokYangDikurangi = null;
                    int jumlahMutasiStok;
                    int totalMutasiStok;
                    foreach (TransaksiLayanan tl in pTransaksi.TransaksiLayanan)
                    {
                        if (tl.JumlahFreeGift > 0)
                        {
                            totalMutasiStok = tl.JumlahFreeGift;
                            while (totalMutasiStok > 0)
                            {
                                stokYangDikurangi = (from stok in context.Stok
                                                     where stok.IdJenisStok == tl.IdJenisStok
                                                     orderby stok.TanggalKadaluarsa
                                                     select stok).FirstOrDefault();
                                if (stokYangDikurangi != null)
                                {
                                    if (stokYangDikurangi.JumlahAktual >= totalMutasiStok)
                                    {
                                        jumlahMutasiStok = totalMutasiStok;
                                        stokYangDikurangi.JumlahAktual -= totalMutasiStok;
                                        totalMutasiStok = 0;
                                    }
                                    else
                                    {
                                        jumlahMutasiStok = stokYangDikurangi.JumlahAktual;
                                        totalMutasiStok -= stokYangDikurangi.JumlahAktual;
                                        stokYangDikurangi.JumlahAktual = 0;
                                    }
                                    mutasiStok = context.MutasiStok.CreateObject();
                                    mutasiStok.IdStok = stokYangDikurangi.IdStok;
                                    //mutasiStok.IdUser = SessionController.CurrentUser.IdUser;
                                    mutasiStok.JumlahMutasi = jumlahMutasiStok;
                                    mutasiStok.Keterangan = "Free Gift";
                                    mutasiStok.LastUpdated = DateTime.Now;
                                    mutasiStok.WaktuMutasi = DateTime.Now;
                                    context.MutasiStok.AddObject(mutasiStok);
                                }
                                else
                                {
                                    totalMutasiStok = 0;
                                }
                            }
                        }
                    }

                    mutasiStok = null;
                    stokYangDikurangi = null;
                    jumlahMutasiStok = 0; //nilai yang akan dikurangkan ke stok dengan id tertentu
                    totalMutasiStok = 0; //nilai pengurangan yang harus dikurangkan lagi
                    foreach (TransaksiProduk tp in pTransaksi.TransaksiProduk)
                    {
                        if (tp.JumlahProduk > 0)
                        {
                            totalMutasiStok = tp.JumlahProduk;
                            while (totalMutasiStok > 0)
                            {
                                stokYangDikurangi = (from stok in context.Stok
                                                    where stok.IdJenisStok == tp.IdJenisStok
                                                    orderby stok.TanggalKadaluarsa
                                                    select stok).FirstOrDefault();
                                if (stokYangDikurangi != null)
                                {
                                    if (stokYangDikurangi.JumlahAktual >= totalMutasiStok)
                                    {
                                        jumlahMutasiStok = totalMutasiStok;
                                        stokYangDikurangi.JumlahAktual -= totalMutasiStok;
                                        totalMutasiStok = 0;
                                    }
                                    else
                                    {
                                        jumlahMutasiStok = stokYangDikurangi.JumlahAktual;
                                        totalMutasiStok -= stokYangDikurangi.JumlahAktual;
                                        stokYangDikurangi.JumlahAktual = 0;
                                    }
                                    mutasiStok = context.MutasiStok.CreateObject();
                                    mutasiStok.IdStok = stokYangDikurangi.IdStok;
                                    //mutasiStok.IdUser = SessionController.CurrentUser.IdUser;
                                    mutasiStok.JumlahMutasi = jumlahMutasiStok;
                                    mutasiStok.Keterangan = "Pembelian Produk";
                                    mutasiStok.LastUpdated = DateTime.Now;
                                    mutasiStok.WaktuMutasi = DateTime.Now;
                                    context.MutasiStok.AddObject(mutasiStok);
                                }
                                else
                                {
                                    totalMutasiStok = 0;
                                }
                            }
                        }
                    }
                    context.SaveChanges();
                    retval = pTransaksi;
                }
            }
            catch (Exception) {}
            return retval;
        }

        private Transaksi CancelTransaksiInternal(int idTransaksi)
        {
            Transaksi retval = null;
            try 
	        {
                using (AnataEntities context = new AnataEntities())
                {
                    retval = (from trans in context.Transaksi
                             where trans.IdTransaksi == idTransaksi
                             select trans).FirstOrDefault();
                    retval.WaktuSelesai = DateTime.Now;
                    retval.IsBatal = true;

                    foreach (var transaksiLayanan in retval.TransaksiLayanan) {
                        transaksiLayanan.WaktuSelesai = DateTime.Now;
                        transaksiLayanan.IsBatal = true;
                    }
                }
	        }
	        catch (Exception) {}
            return retval;
        }
        */

        private List<TransaksiThumbnailViewModel> FetchTransaksiTVMsInternal(int page)
        {
            List<TransaksiThumbnailViewModel> retval = new List<TransaksiThumbnailViewModel>();
            TransaksiThumbnailViewModel tempTTVM = null;
            try
            {
                int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
                using (AnataEntities context = new AnataEntities())
                {
                    var query = from transaksi in context.Transaksi
                                orderby transaksi.WaktuSelesai != null, transaksi.WaktuSelesai, transaksi.WaktuBuat
                                select transaksi;
                    foreach (var transaksi in query.ToList().Skip(page * pageSize).Take(pageSize))
                    {
                        tempTTVM = new TransaksiThumbnailViewModel();
                        SynchTransaksiToTTVM(transaksi, tempTTVM);
                        retval.Add(tempTTVM);
                    }
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiThumbnailViewModel LoadTransaksiTVMInternal(TransaksiThumbnailViewModel ttvm)
        {
            TransaksiThumbnailViewModel retval = ttvm;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi originalT = context.Transaksi.FirstOrDefault(
                        t => t.IdTransaksi == ttvm.IdTransaksi);
                    SynchTransaksiToTTVM(originalT, ttvm);
                    retval = ttvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiThumbnailViewModel SaveTransaksiTVMInternal(TransaksiThumbnailViewModel ttvm)
        {
            TransaksiThumbnailViewModel retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi originalT = null;
                    List<int> originalTLs = new List<int>();
                    List<int> originalTPs = new List<int>();
                    List<int> originalTBs = new List<int>();
                    if (ttvm.IdTransaksi != 0)
                    {
                        originalT = context.Transaksi.FirstOrDefault(
                            t => t.IdTransaksi == ttvm.IdTransaksi);
                        foreach (var tl in originalT.TransaksiLayanan)
                        {
                            originalTLs.Add(tl.IdTransaksiLayanan);
                        }
                        foreach (var tp in originalT.TransaksiProduk)
                        {
                            originalTPs.Add(tp.IdTransaksiProduk);
                        }
                        foreach (var tb in originalT.TransaksiPembayaran)
                        {
                            originalTBs.Add(tb.IdTransaksiPembayaran);
                        }
                    }
                    else
                    {
                        originalT = context.Transaksi.CreateObject();
                        context.Transaksi.AddObject(originalT);
                        //TODO: Id Cabang & User
                        originalT.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
                        originalT.WaktuBuat = DateTime.Now;
                        //originalT.IdUser = SessionController.Instance.LoggedUserId;
                        originalT.LastUpdated = DateTime.Now;
                    }
                    originalT.IdKonsumen = ttvm.IdKonsumen;
                    originalT.WaktuSelesai = ttvm.WaktuSelesai;
                    originalT.TotalHarga = ttvm.TotalHarga;
                    originalT.PotonganHarga = ttvm.TotalPotongan;
                    originalT.KoreksiHarga = ttvm.KoreksiHarga;
                    originalT.IsBatal = ttvm.IsBatal;

                    if (originalT.EntityState == EntityState.Modified)
                    {
                        //originalT.IdUser = SessionController.Instance.LoggedUserId;
                        originalT.LastUpdated = DateTime.Now;
                    }

                    TransaksiLayanan originalTL = null;
                    foreach (TransaksiLayananThumbnailViewModel tltvm in ttvm.TransaksiLayanans)
                    {
                        if (originalTLs.Remove(tltvm.IdTransaksiLayanan))
                        {
                            originalTL = originalT.TransaksiLayanan.FirstOrDefault(
                                tl => tl.IdTransaksiLayanan == tltvm.IdTransaksiLayanan);
                        }
                        else
                        {
                            originalTL = context.TransaksiLayanan.CreateObject();
                            context.TransaksiLayanan.AddObject(originalTL);
                            originalT.TransaksiLayanan.Add(originalTL);
                            originalTL.WaktuBuat = DateTime.Now;
                            //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                            originalTL.LastUpdated = DateTime.Now;
                        }
                        originalTL.IdLayanan = tltvm.IdLayanan;
                        originalTL.HargaLayanan = tltvm.HargaLayanan;
                        originalTL.IdKaryawan = tltvm.IdKaryawan;
                        originalTL.NamaPromo = tltvm.NamaPromo;
                        originalTL.PotonganPromo = tltvm.PotonganPromo;
                        originalTL.NamaFreeGift = tltvm.NamaFreeGift;
                        originalTL.IdJenisStok = tltvm.IdJenisStok;
                        originalTL.JumlahFreeGift = tltvm.JumlahFreeGift;
                        originalTL.WaktuBuat = tltvm.WaktuBuat;
                        originalTL.WaktuTunggu = tltvm.WaktuTunggu;
                        originalTL.WaktuMulai = tltvm.WaktuMulai;
                        originalTL.WaktuSelesai = tltvm.WaktuSelesai;
                        originalTL.IsBatal = tltvm.IsBatal;

                        if (originalTL.EntityState == EntityState.Modified)
                        {
                            //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                            originalTL.LastUpdated = DateTime.Now;
                        }
                    }
                    //clearing
                    foreach (int removedId in originalTLs)
                    {
                        context.TransaksiLayanan.DeleteObject(
                            originalT.TransaksiLayanan.FirstOrDefault(
                                tl => tl.IdTransaksiLayanan == removedId));
                    }

                    TransaksiProduk originalTP = null;
                    foreach (TransaksiProdukThumbnailViewModel tptvm in ttvm.TransaksiProduks)
                    {
                        if (originalTPs.Remove(tptvm.IdTransaksiProduk))
                        {
                            originalTP = originalT.TransaksiProduk.FirstOrDefault(
                                tp => tp.IdTransaksiProduk == tptvm.IdTransaksiProduk);
                        }
                        else
                        {
                            originalTP = context.TransaksiProduk.CreateObject();
                            context.TransaksiProduk.AddObject(originalTP);
                            originalT.TransaksiProduk.Add(originalTP);
                            //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                            originalTP.LastUpdated = DateTime.Now;
                        }
                        originalTP.IdJenisStok = tptvm.IdJenisStok;
                        originalTP.IdKaryawan = tptvm.IdKaryawan;
                        originalTP.JumlahProduk = tptvm.JumlahProduk;
                        originalTP.HargaProduk = tptvm.HargaProduk;
                        originalTP.PotonganHarga = tptvm.PotonganHarga;
                        originalTP.IsBatal = tptvm.IsBatal;
                        originalTP.WaktuBatal = tptvm.WaktuBatal;

                        if (originalTP.EntityState == EntityState.Modified)
                        {
                            //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                            originalTP.LastUpdated = DateTime.Now;
                        }
                    }
                    //clearing
                    foreach (int removedId in originalTPs)
                    {
                        context.TransaksiProduk.DeleteObject(
                            originalT.TransaksiProduk.FirstOrDefault(
                                tp => tp.IdTransaksiProduk == removedId));
                    }

                    TransaksiPembayaran originalTB = null;
                    foreach (TransaksiPembayaranThumbnailViewModel tbtvm in ttvm.TransaksiPembayarans)
                    {
                        if (originalTBs.Remove(tbtvm.IdTransaksiPembayaran))
                        {
                            originalTB = originalT.TransaksiPembayaran.FirstOrDefault(
                                tb => tb.IdTransaksiPembayaran == tbtvm.IdTransaksiPembayaran);
                        }
                        else
                        {
                            originalTB = context.TransaksiPembayaran.CreateObject();
                            context.TransaksiPembayaran.AddObject(originalTB);
                            originalT.TransaksiPembayaran.Add(originalTB);
                            //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                            originalTB.LastUpdated = DateTime.Now;
                        }
                        originalTB.IdJenisPembayaran = tbtvm.IdJenisPembayaran;
                        originalTB.NominalPembayaran = tbtvm.NominalPembayaran;

                        if (originalTB.EntityState == EntityState.Modified)
                        {
                            //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                            originalTB.LastUpdated = DateTime.Now;
                        }
                    }
                    //clearing
                    foreach (int removedId in originalTBs)
                    {
                        context.TransaksiPembayaran.DeleteObject(
                            originalT.TransaksiPembayaran.FirstOrDefault(
                                tl => tl.IdTransaksiPembayaran == removedId));
                    }
                    context.SaveChanges();

                    //update ids ++ synch
                    SynchTransaksiToTTVM(originalT, ttvm);
                    retval = ttvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiViewModel LoadTransaksiVMInternal(TransaksiViewModel tvm)
        {
            TransaksiViewModel retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi originalT = context.Transaksi.FirstOrDefault(
                            t => t.IdTransaksi == tvm.IdTransaksi.DataValue);
                    SynchTransaksiToTVM(originalT, tvm);
                    retval = tvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiViewModel SaveTransaksiVMInternal(TransaksiViewModel tvm)
        {
            TransaksiViewModel retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi originalT = null;
                    List<int> originalTLs = new List<int>();
                    List<int> originalTPs = new List<int>();
                    List<int> originalTBs = new List<int>();
                    if (tvm.IdTransaksi.DataValue != 0)
                    {
                        originalT = context.Transaksi.FirstOrDefault(
                            t => t.IdTransaksi == tvm.IdTransaksi.DataValue);
                        foreach (var tl in originalT.TransaksiLayanan)
                        {
                            originalTLs.Add(tl.IdTransaksiLayanan);
                        }
                        foreach (var tp in originalT.TransaksiProduk)
                        {
                            originalTPs.Add(tp.IdTransaksiProduk);
                        }
                        foreach (var tb in originalT.TransaksiPembayaran)
                        {
                            originalTBs.Add(tb.IdTransaksiPembayaran);
                        }
                    }
                    else
                    {
                        originalT = context.Transaksi.CreateObject();
                        context.Transaksi.AddObject(originalT);
                        //TODO: Id Cabang & User
                        originalT.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
                        originalT.WaktuBuat = DateTime.Now;
                        //originalTransaksi.IdUser = SessionController.Instance.LoggedUserId;
                        originalT.LastUpdated = DateTime.Now;
                    }
                    originalT.IdKonsumen = tvm.IdKonsumen.DataValue;
                    originalT.WaktuSelesai = tvm.WaktuSelesai.DataValue;
                    originalT.TotalHarga = tvm.TotalHarga;
                    originalT.PotonganHarga = tvm.TotalPotongan;
                    originalT.KoreksiHarga = tvm.KoreksiHarga.DataValue;
                    originalT.IsBatal = tvm.IsBatal.DataValue;

                    if (originalT.EntityState == EntityState.Modified)
                    {
                        //originalT.IdUser = SessionController.Instance.LoggedUserId;
                        originalT.LastUpdated = DateTime.Now;
                    }

                    TransaksiLayanan originalTL = null;
                    foreach (TransaksiLayananViewModel tlvm in tvm.TransaksiLayanans)
                    {
                        if (originalTLs.Remove(tlvm.IdTransaksiLayanan.DataValue))
                        {
                            originalTL = originalT.TransaksiLayanan.FirstOrDefault(
                                tl => tl.IdTransaksiLayanan == tlvm.IdTransaksiLayanan.DataValue);
                        }
                        else
                        {
                            originalTL = context.TransaksiLayanan.CreateObject();
                            context.TransaksiLayanan.AddObject(originalTL);
                            originalT.TransaksiLayanan.Add(originalTL);
                            originalTL.WaktuBuat = DateTime.Now;
                            //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                            originalTL.LastUpdated = DateTime.Now;
                        }
                        originalTL.IdLayanan = tlvm.IdLayanan.DataValue;
                        originalTL.HargaLayanan = tlvm.HargaLayanan;
                        originalTL.IdKaryawan = tlvm.IdKaryawan.DataValue;
                        originalTL.NamaPromo = tlvm.NamaPromo.DataValue;
                        originalTL.PotonganPromo = tlvm.PotonganPromo.DataValue;
                        originalTL.NamaFreeGift = tlvm.NamaFreeGift.DataValue;
                        originalTL.IdJenisStok = tlvm.IdJenisStok.DataValue;
                        originalTL.JumlahFreeGift = tlvm.JumlahFreeGift.DataValue;
                        originalTL.WaktuBuat = tlvm.WaktuBuat.DataValue;
                        originalTL.WaktuTunggu = tlvm.WaktuTunggu.DataValue;
                        originalTL.WaktuMulai = tlvm.WaktuMulai.DataValue;
                        originalTL.WaktuSelesai = tlvm.WaktuSelesai.DataValue;
                        originalTL.IsBatal = tlvm.IsBatal.DataValue;

                        if (originalTL.EntityState == EntityState.Modified)
                        {
                            //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                            originalTL.LastUpdated = DateTime.Now;
                        }
                    }
                    //clearing
                    foreach (int removedId in originalTLs)
                    {
                        context.TransaksiLayanan.DeleteObject(
                            originalT.TransaksiLayanan.FirstOrDefault(
                                tl => tl.IdTransaksiLayanan == removedId));
                    }

                    TransaksiProduk originalTP = null;
                    foreach (TransaksiProdukViewModel tpvm in tvm.TransaksiProduks)
                    {
                        if (originalTPs.Remove(tpvm.IdTransaksiProduk.DataValue))
                        {
                            originalTP = originalT.TransaksiProduk.FirstOrDefault(
                                tp => tp.IdTransaksiProduk == tpvm.IdTransaksiProduk.DataValue);
                        }
                        else
                        {
                            originalTP = context.TransaksiProduk.CreateObject();
                            context.TransaksiProduk.AddObject(originalTP);
                            originalT.TransaksiProduk.Add(originalTP);
                            //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                            originalTP.LastUpdated = DateTime.Now;
                        }
                        originalTP.IdJenisStok = tpvm.IdJenisStok.DataValue;
                        originalTP.IdKaryawan = tpvm.IdKaryawan.DataValue;
                        originalTP.JumlahProduk = tpvm.JumlahProduk.DataValue;
                        originalTP.HargaProduk = tpvm.HargaProduk.DataValue;
                        originalTP.PotonganHarga = tpvm.PotonganHarga.DataValue;
                        originalTP.IsBatal = tpvm.IsBatal.DataValue;
                        originalTP.WaktuBatal = tpvm.WaktuBatal.DataValue;

                        if (originalTP.EntityState == EntityState.Modified)
                        {
                            //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                            originalTP.LastUpdated = DateTime.Now;
                        }
                    }
                    //clearing
                    foreach (int removedId in originalTPs)
                    {
                        context.TransaksiProduk.DeleteObject(
                            originalT.TransaksiProduk.FirstOrDefault(
                                tp => tp.IdTransaksiProduk == removedId));
                    }

                    TransaksiPembayaran originalTB = null;
                    foreach (TransaksiPembayaranViewModel tbvm in tvm.TransaksiPembayarans)
                    {
                        if (originalTBs.Remove(tbvm.IdTransaksiPembayaran.DataValue))
                        {
                            originalTB = originalT.TransaksiPembayaran.FirstOrDefault(
                                tb => tb.IdTransaksiPembayaran == tbvm.IdTransaksiPembayaran.DataValue);
                        }
                        else
                        {
                            originalTB = context.TransaksiPembayaran.CreateObject();
                            context.TransaksiPembayaran.AddObject(originalTB);
                            originalT.TransaksiPembayaran.Add(originalTB);
                            //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                            originalTB.LastUpdated = DateTime.Now;
                        }
                        originalTB.IdJenisPembayaran = tbvm.IdJenisPembayaran.DataValue;
                        originalTB.NominalPembayaran = tbvm.NominalPembayaran.DataValue;

                        if (originalTB.EntityState == EntityState.Modified)
                        {
                            //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                            originalTB.LastUpdated = DateTime.Now;
                        }
                    }
                    //clearing
                    foreach (int removedId in originalTBs)
                    {
                        context.TransaksiPembayaran.DeleteObject(
                            originalT.TransaksiPembayaran.FirstOrDefault(
                                tb => tb.IdTransaksiPembayaran == removedId));
                    }
                    context.SaveChanges();

                    //update ids ++ synch
                    SynchTransaksiToTVM(originalT, tvm);
                    retval = tvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiViewModel LoadPembayaranVMInternal(TransaksiViewModel tvm)
        {
            TransaksiViewModel retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi originalT = context.Transaksi.FirstOrDefault(
                            t => t.IdTransaksi == tvm.IdTransaksi.DataValue);
                    tvm.IdKonsumen.DataValue = originalT.IdKonsumen;
                    tvm.NamaKonsumen = originalT.Konsumen.Nama;
                    tvm.AlamatKonsumen = originalT.Konsumen.Alamat;
                    tvm.TeleponKonsumen = originalT.Konsumen.NoTelepon;
                    tvm.IdCabang.DataValue = originalT.IdCabang;
                    tvm.WaktuBuat.DataValue = originalT.WaktuBuat;
                    tvm.WaktuSelesai.DataValue = originalT.WaktuSelesai;
                    tvm.KoreksiHarga.DataValue = originalT.KoreksiHarga;
                    tvm.IsBatal.DataValue = originalT.IsBatal;

                    tvm.TransaksiLayanans.Clear();
                    TransaksiLayananViewModel tlvm = null;
                    //foreach (var tl in originalT.TransaksiLayanan
                    //    .Where(tl => !tl.IsBatal)
                    //    .OrderBy(tl => tl.WaktuSelesai)
                    //    .ThenBy(tl => tl.WaktuMulai == null)
                    //    .ThenBy(tl => tl.WaktuMulai)
                    //    .ThenBy(tl => tl.WaktuTunggu == null)
                    //    .ThenBy(tl => tl.WaktuTunggu)
                    //    .ThenBy(tl => tl.WaktuBuat))
                    foreach (var tl in (from t in originalT.TransaksiLayanan
                                        where !t.IsBatal
                                        orderby t.WaktuSelesai, t.WaktuMulai, t.WaktuTunggu, t.WaktuBuat
                                        select t).ToList())
                    {
                        tlvm = tvm.ForceCreateChildTransaksiLayananVM();
                        tlvm.IdTransaksiLayanan.DataValue = tl.IdTransaksiLayanan;
                        tlvm.IdTransaksi.DataValue = tl.IdTransaksi;
                        tlvm.IdLayanan.DataValue = tl.IdLayanan;
                        tlvm.NamaLayanan = tl.Layanan.Nama;
                        tlvm.HargaLayanan = tl.HargaLayanan;
                        tlvm.IdKaryawan.DataValue = tl.IdKaryawan;
                        tlvm.NamaKaryawan = tl.Karyawan.Nama;
                        tlvm.NamaPromo.DataValue = tl.NamaPromo;
                        tlvm.PotonganPromo.DataValue = tl.PotonganPromo;
                        tlvm.NamaFreeGift.DataValue = tl.NamaFreeGift;
                        tlvm.IdJenisStok.DataValue = tl.IdJenisStok;
                        if (tl.IdJenisStok.HasValue)
                        {
                            tlvm.NamaJenisStok = tl.JenisStok.Nama;
                        }
                        tlvm.JumlahFreeGift.DataValue = tl.JumlahFreeGift;
                        tlvm.NilaiKepuasan.DataValue = tl.NilaiKepuasan;
                        tlvm.WaktuBuat.DataValue = tl.WaktuBuat;
                        tlvm.WaktuTunggu.DataValue = tl.WaktuTunggu;
                        tlvm.WaktuMulai.DataValue = tl.WaktuMulai;
                        tlvm.WaktuSelesai.DataValue = tl.WaktuSelesai;
                        tlvm.IsBatal.DataValue = tl.IsBatal;
                        tlvm.PreviousStatusTransaksiLayanan = tlvm.StatusTransaksiLayanan;
                        tvm.TransaksiLayanans.Add(tlvm);
                    }

                    tvm.TransaksiProduks.Clear();
                    TransaksiProdukViewModel tpvm = null;
                    foreach (var tp in originalT.TransaksiProduk
                        .Where(tp => !tp.IsBatal))
                    {
                        tpvm = tvm.ForceCreateChildTransaksiProdukVM();
                        tpvm.IdTransaksiProduk.DataValue = tp.IdTransaksiProduk;
                        tpvm.IdTransaksi.DataValue = tp.IdTransaksi;
                        tpvm.IdJenisStok.DataValue = tp.IdJenisStok;
                        tpvm.NamaJenisStok = tp.JenisStok.Nama;
                        tpvm.IdKaryawan.DataValue = tp.IdKaryawan;
                        tpvm.NamaKaryawan = tp.Karyawan.Nama;
                        tpvm.JumlahProduk.DataValue = tp.JumlahProduk;
                        tpvm.HargaProduk.DataValue = tp.HargaProduk;
                        tpvm.PotonganHarga.DataValue = tp.PotonganHarga;
                        tpvm.IsBatal.DataValue = tp.IsBatal;
                        tpvm.WaktuBatal.DataValue = tp.WaktuBatal;
                        tpvm.PreviousStatusTransaksiProduk = tpvm.StatusTransaksiProduk;
                        tvm.TransaksiProduks.Add(tpvm);
                    }

                    tvm.TransaksiPembayarans.Clear();
                    TransaksiPembayaranViewModel tbvm = null;
                    foreach (var tb in originalT.TransaksiPembayaran)
                    {
                        tbvm = tvm.ForceCreateChildTransaksiPembayaranVM();
                        tbvm.IdTransaksiPembayaran.DataValue = tb.IdTransaksiPembayaran;
                        tbvm.IdTransaksi.DataValue = tb.IdTransaksi;
                        tbvm.IdJenisPembayaran.DataValue = tb.IdJenisPembayaran;
                        tbvm.NamaJenisPembayaran = tb.JenisPembayaran.Nama;
                        tbvm.NominalPembayaran.DataValue = tb.NominalPembayaran;
                        tvm.TransaksiPembayarans.Add(tbvm);
                    }
                    retval = tvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiViewModel SavePembayaranVMInternal(TransaksiViewModel tvm)
        {
            TransaksiViewModel retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi original = null;
                    SynchTVMToTransaksi(tvm, out original, context);
                    original.WaktuSelesai = DateTime.Now;

                    #region Penambahan / Pengurangan kas
                    Int64 totalPembayaran = 0;
                    Int64 totalPembayaranTunai = 0;
                    foreach (TransaksiPembayaran tp in original.TransaksiPembayaran)
                    {
                        totalPembayaran += tp.NominalPembayaran;
                        if (tp.JenisPembayaran.IsTunai)
                        {
                            totalPembayaranTunai += tp.NominalPembayaran;
                        }
                    }
                    MutasiRekening mutasiKas = context.MutasiRekening.CreateObject();
                    mutasiKas.IdCabang = original.IdCabang;
                    mutasiKas.IsOtomatis = true;
                    mutasiKas.NominalMutasi = totalPembayaranTunai - (totalPembayaran - original.TotalHarga);
                    //TODO: get current session user
                    //mutasi.IdUser = SessionController.CurrentUser.IdUser;
                    mutasiKas.LastUpdated = DateTime.Now;
                    context.MutasiRekening.AddObject(mutasiKas);
                    #endregion

                    #region Pengurangan Stok dari Free Gift
                    MutasiStok mutasiStok = null;
                    Stok stokYangDikurangi = null;
                    int jumlahStokTersedia;
                    int jumlahMutasiStok;
                    int totalMutasiStok;
                    foreach (TransaksiLayanan tl in original.TransaksiLayanan)
                    {
                        if (tl.JumlahFreeGift > 0)
                        {
                            totalMutasiStok = tl.JumlahFreeGift;
                            var stoks = (from stok in context.Stok
                                         where stok.IdJenisStok == tl.IdJenisStok
                                         orderby stok.TanggalKadaluarsa
                                         select stok).ToList();
                            while (totalMutasiStok > 0)
                            {
                                stokYangDikurangi = stoks.First();
                                if (stokYangDikurangi != null)
                                {
                                    jumlahStokTersedia = stokYangDikurangi.JumlahBeli - stokYangDikurangi.SumJumlahMutasiStok - stokYangDikurangi.MutasiStok.Sum(ms => ms.JumlahMutasi);
                                    if (jumlahStokTersedia >= totalMutasiStok)
                                    {
                                        jumlahMutasiStok = totalMutasiStok;
                                        jumlahStokTersedia -= totalMutasiStok;
                                        totalMutasiStok = 0;
                                    }
                                    else
                                    {
                                        jumlahMutasiStok = jumlahStokTersedia;
                                        totalMutasiStok -= jumlahStokTersedia;
                                        jumlahStokTersedia = 0;
                                    }
                                    mutasiStok = context.MutasiStok.CreateObject();
                                    mutasiStok.IdStok = stokYangDikurangi.IdStok;
                                    //mutasiStok.IdUser = SessionController.CurrentUser.IdUser;
                                    mutasiStok.JumlahMutasi = jumlahMutasiStok;
                                    mutasiStok.Keterangan = "Free Gift";
                                    mutasiStok.LastUpdated = DateTime.Now;
                                    mutasiStok.WaktuMutasi = DateTime.Now;
                                    context.MutasiStok.AddObject(mutasiStok);
                                }
                                else
                                {
                                    totalMutasiStok = 0;
                                }
                            }
                        }
                    }
                    #endregion

                    #region Pengurangan Stok dari Penjualan Produk
                    mutasiStok = null;
                    stokYangDikurangi = null;
                    jumlahStokTersedia = 0;
                    jumlahMutasiStok = 0; //nilai yang akan dikurangkan ke stok dengan id tertentu
                    totalMutasiStok = 0; //nilai pengurangan yang harus dikurangkan lagi
                    foreach (TransaksiProduk tp in original.TransaksiProduk)
                    {
                        if (tp.JumlahProduk > 0)
                        {
                            totalMutasiStok = tp.JumlahProduk;
                            var stoks = (from stok in context.Stok
                                         where stok.IdJenisStok == tp.IdJenisStok
                                         orderby stok.TanggalKadaluarsa
                                         select stok).ToList();
                            while (totalMutasiStok > 0)
                            {
                                stokYangDikurangi = stoks.First();
                                if (stokYangDikurangi != null)
                                {
                                    jumlahStokTersedia = stokYangDikurangi.JumlahBeli - stokYangDikurangi.SumJumlahMutasiStok - stokYangDikurangi.MutasiStok.Sum(ms => ms.JumlahMutasi);
                                    if (jumlahStokTersedia >= totalMutasiStok)
                                    {
                                        jumlahMutasiStok = totalMutasiStok;
                                        jumlahStokTersedia -= totalMutasiStok;
                                        totalMutasiStok = 0;
                                    }
                                    else
                                    {
                                        jumlahMutasiStok = jumlahStokTersedia;
                                        totalMutasiStok -= jumlahStokTersedia;
                                        jumlahStokTersedia = 0;
                                    }
                                    mutasiStok = context.MutasiStok.CreateObject();
                                    mutasiStok.IdStok = stokYangDikurangi.IdStok;
                                    //mutasiStok.IdUser = SessionController.CurrentUser.IdUser;
                                    mutasiStok.JumlahMutasi = jumlahMutasiStok;
                                    mutasiStok.Keterangan = "Pembelian Produk";
                                    mutasiStok.LastUpdated = DateTime.Now;
                                    mutasiStok.WaktuMutasi = DateTime.Now;
                                    context.MutasiStok.AddObject(mutasiStok);
                                }
                                else
                                {
                                    totalMutasiStok = 0;
                                }
                            }
                        }
                    }
                    #endregion

                    context.SaveChanges();

                    //update ids ++ synch
                    SynchTransaksiToTVM(original, tvm);
                    retval = tvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        private TransaksiViewModel PayTransaksiVMInternal(TransaksiViewModel tvm)
        {
            TransaksiViewModel retval = null;
            try
            {
                using (AnataEntities context = new AnataEntities())
                {
                    Transaksi original = null;
                    SynchTVMToTransaksi(tvm, out original, context);
                    original.WaktuSelesai = DateTime.Now;

                    #region Penambahan / Pengurangan kas
                    Int64 totalPembayaran = 0;
                    Int64 totalPembayaranTunai = 0;
                    foreach (TransaksiPembayaran tp in original.TransaksiPembayaran)
                    {
                        totalPembayaran += tp.NominalPembayaran;
                        if (tp.JenisPembayaran.IsTunai) {
                            totalPembayaranTunai += tp.NominalPembayaran;
                        }
                    }
                    MutasiRekening mutasiKas = context.MutasiRekening.CreateObject();
                    mutasiKas.IdCabang = original.IdCabang;
                    mutasiKas.IsOtomatis = true;
                    mutasiKas.NominalMutasi = totalPembayaranTunai - (totalPembayaran - original.TotalHarga);
                    //TODO: get current session user
                    //mutasi.IdUser = SessionController.CurrentUser.IdUser;
                    mutasiKas.LastUpdated = DateTime.Now;
                    context.MutasiRekening.AddObject(mutasiKas);
                    #endregion

                    #region Pengurangan Stok dari Free Gift
                    MutasiStok mutasiStok = null;
                    Stok stokYangDikurangi = null;
                    int jumlahStokTersedia;
                    int jumlahMutasiStok;
                    int totalMutasiStok;
                    foreach (TransaksiLayanan tl in original.TransaksiLayanan)
                    {
                        if (tl.JumlahFreeGift > 0)
                        {
                            totalMutasiStok = tl.JumlahFreeGift;
                            var stoks = (from stok in context.Stok
                                         where stok.IdJenisStok == tl.IdJenisStok
                                         orderby stok.TanggalKadaluarsa
                                         select stok).ToList();
                            while (totalMutasiStok > 0)
                            {
                                stokYangDikurangi = stoks.First();
                                if (stokYangDikurangi != null)
                                {
                                    jumlahStokTersedia = stokYangDikurangi.JumlahBeli - stokYangDikurangi.SumJumlahMutasiStok - stokYangDikurangi.MutasiStok.Sum(ms => ms.JumlahMutasi);
                                    if (jumlahStokTersedia >= totalMutasiStok)
                                    {
                                        jumlahMutasiStok = totalMutasiStok;
                                        jumlahStokTersedia -= totalMutasiStok;
                                        totalMutasiStok = 0;
                                    }
                                    else
                                    {
                                        jumlahMutasiStok = jumlahStokTersedia;
                                        totalMutasiStok -= jumlahStokTersedia;
                                        jumlahStokTersedia = 0;
                                    }
                                    mutasiStok = context.MutasiStok.CreateObject();
                                    mutasiStok.IdStok = stokYangDikurangi.IdStok;
                                    //mutasiStok.IdUser = SessionController.CurrentUser.IdUser;
                                    mutasiStok.JumlahMutasi = jumlahMutasiStok;
                                    mutasiStok.Keterangan = "Free Gift";
                                    mutasiStok.LastUpdated = DateTime.Now;
                                    mutasiStok.WaktuMutasi = DateTime.Now;
                                    context.MutasiStok.AddObject(mutasiStok);
                                }
                                else
                                {
                                    totalMutasiStok = 0;
                                }
                            }
                        }
                    }
                    #endregion

                    #region Pengurangan Stok dari Penjualan Produk
                    mutasiStok = null;
                    stokYangDikurangi = null;
                    jumlahStokTersedia = 0;
                    jumlahMutasiStok = 0; //nilai yang akan dikurangkan ke stok dengan id tertentu
                    totalMutasiStok = 0; //nilai pengurangan yang harus dikurangkan lagi
                    foreach (TransaksiProduk tp in original.TransaksiProduk)
                    {
                        if (tp.JumlahProduk > 0)
                        {
                            totalMutasiStok = tp.JumlahProduk;
                            var stoks = (from stok in context.Stok
                                         where stok.IdJenisStok == tp.IdJenisStok
                                         orderby stok.TanggalKadaluarsa
                                         select stok).ToList();
                            while (totalMutasiStok > 0)
                            {
                                stokYangDikurangi = stoks.First();
                                if (stokYangDikurangi != null)
                                {
                                    jumlahStokTersedia = stokYangDikurangi.JumlahBeli - stokYangDikurangi.SumJumlahMutasiStok - stokYangDikurangi.MutasiStok.Sum(ms => ms.JumlahMutasi);
                                    if (jumlahStokTersedia >= totalMutasiStok)
                                    {
                                        jumlahMutasiStok = totalMutasiStok;
                                        jumlahStokTersedia -= totalMutasiStok;
                                        totalMutasiStok = 0;
                                    }
                                    else
                                    {
                                        jumlahMutasiStok = jumlahStokTersedia;
                                        totalMutasiStok -= jumlahStokTersedia;
                                        jumlahStokTersedia = 0;
                                    }
                                    mutasiStok = context.MutasiStok.CreateObject();
                                    mutasiStok.IdStok = stokYangDikurangi.IdStok;
                                    //mutasiStok.IdUser = SessionController.CurrentUser.IdUser;
                                    mutasiStok.JumlahMutasi = jumlahMutasiStok;
                                    mutasiStok.Keterangan = "Pembelian Produk";
                                    mutasiStok.LastUpdated = DateTime.Now;
                                    mutasiStok.WaktuMutasi = DateTime.Now;
                                    context.MutasiStok.AddObject(mutasiStok);
                                }
                                else
                                {
                                    totalMutasiStok = 0;
                                }
                            }
                        }
                    }
                    #endregion

                    context.SaveChanges();

                    //update ids ++ synch
                    SynchTransaksiToTVM(original, tvm);
                    retval = tvm;
                }
            }
            catch (Exception) { }
            return retval;
        }
        #endregion

        #region PrivateMethods.Synchronizer
        /*
        private Transaksi SynchTransaksi(Transaksi updatedTransaksi, AnataEntities context)
        {
            //TODO:
            Transaksi originalTransaksi = null;
            List<int> originalTLs = new List<int>();
            List<int> originalTPs = new List<int>();
            List<int> originalTBs = new List<int>();
            if (updatedTransaksi.IdTransaksi != 0) {
                originalTransaksi = (from t in context.Transaksi
                                    where t.IdTransaksi == updatedTransaksi.IdTransaksi
                                    select t).First();
                originalTLs = (from tl in context.TransaksiLayanan
                               where tl.IdTransaksi == updatedTransaksi.IdTransaksi
                               select tl.IdTransaksiLayanan).ToList();
                originalTPs = (from tp in context.TransaksiProduk
                               where tp.IdTransaksi == updatedTransaksi.IdTransaksi
                               select tp.IdTransaksiProduk).ToList();
                originalTBs = (from tb in context.TransaksiPembayaran
                               where tb.IdTransaksi == updatedTransaksi.IdTransaksi
                               select tb.IdTransaksiPembayaran).ToList();
            } else {
                originalTransaksi = context.Transaksi.CreateObject();
                context.Transaksi.AddObject(originalTransaksi);
                //originalTransaksi.WaktuBuat = DateTime.Now;
                //TODO: Id Cabang
                originalTransaksi.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
            }
            //originalTransaksi.IdTransaksi = updatedTransaksi.IdTransaksi;
            originalTransaksi.IdKonsumen = updatedTransaksi.IdKonsumen;
            //originalTransaksi.IdCabang = updatedTransaksi.IdCabang;
            //originalTransaksi.WaktuBuat = updatedTransaksi.WaktuBuat;
            originalTransaksi.WaktuSelesai = updatedTransaksi.WaktuSelesai;
            originalTransaksi.TotalHarga = updatedTransaksi.TotalHarga;
            originalTransaksi.PotonganHarga = updatedTransaksi.PotonganHarga;
            originalTransaksi.KoreksiHarga = updatedTransaksi.KoreksiHarga;
            originalTransaksi.IsBatal = updatedTransaksi.IsBatal;

            if (originalTransaksi.EntityState != EntityState.Unchanged)
            {
                //originalTransaksi.IdUser = SessionController.Instance.LoggedUserId;
                originalTransaksi.LastUpdated = DateTime.Now;
            }

            //originalTransaksi.TransaksiLayanan
            TransaksiLayanan originalTL = null;
            foreach (TransaksiLayanan updatedTL in updatedTransaksi.TransaksiLayanan)
            {
                if (originalTLs.Remove(updatedTL.IdTransaksiLayanan))
                {
                    originalTL = originalTransaksi.TransaksiLayanan.First(
                        tl => tl.IdTransaksiLayanan == updatedTL.IdTransaksiLayanan);
                }
                else
                {
                    originalTL = context.TransaksiLayanan.CreateObject();
                    context.TransaksiLayanan.AddObject(originalTL);
                    originalTransaksi.TransaksiLayanan.Add(originalTL);
                    originalTransaksi.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
                }
                //originalTL.IdTransaksiLayanan = updatedTL.IdTransaksiLayanan;
                //originalTL.IdTransaksi = updatedTL.IdTransaksi;
                originalTL.IdLayanan = updatedTL.IdLayanan;
                originalTL.HargaLayanan = updatedTL.HargaLayanan;
                originalTL.IdKaryawan = updatedTL.IdKaryawan;
                originalTL.NamaPromo = updatedTL.NamaPromo;
                originalTL.PotonganPromo = updatedTL.PotonganPromo;
                originalTL.NamaFreeGift = updatedTL.NamaFreeGift;
                originalTL.IdJenisStok = updatedTL.IdJenisStok;
                originalTL.JumlahFreeGift = updatedTL.JumlahFreeGift;
                originalTL.WaktuBuat = updatedTL.WaktuBuat;
                originalTL.WaktuTunggu = updatedTL.WaktuTunggu;
                originalTL.WaktuMulai = updatedTL.WaktuMulai;
                originalTL.WaktuSelesai = updatedTL.WaktuSelesai;
                originalTL.IsBatal = updatedTL.IsBatal;

                if (originalTransaksi.EntityState != EntityState.Unchanged)
                {
                    //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                    originalTL.LastUpdated = DateTime.Now;
                }
            }
            //clearing
            foreach (int removedId in originalTLs)
            {
                context.TransaksiLayanan.DeleteObject(
                    originalTransaksi.TransaksiLayanan.First(
                    tl => tl.IdTransaksiLayanan == removedId));
            }

            //originalTransaksi.TransaksiProduk.Clear();
            TransaksiProduk originalTP = null;
            foreach (TransaksiProduk updatedTP in updatedTransaksi.TransaksiProduk)
            {
                if (originalTPs.Remove(updatedTP.IdTransaksiProduk))
                {
                    originalTP = originalTransaksi.TransaksiProduk.First(
                        tp => tp.IdTransaksiProduk == updatedTP.IdTransaksiProduk);
                }
                else
                {
                    originalTP = context.TransaksiProduk.CreateObject();
                    context.TransaksiProduk.AddObject(originalTP);
                    originalTransaksi.TransaksiProduk.Add(originalTP);
                    originalTransaksi.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
                }
                //originalTP.IdTransaksiProduk = updatedTP.IdTransaksiProduk;
                //originalTP.IdTransaksi = updatedTP.IdTransaksi;
                originalTP.IdJenisStok = updatedTP.IdJenisStok;
                originalTP.IdKaryawan = updatedTP.IdKaryawan;
                originalTP.JumlahProduk = updatedTP.JumlahProduk;
                originalTP.HargaProduk = updatedTP.HargaProduk;
                originalTP.PotonganHarga = updatedTP.PotonganHarga;

                if (originalTransaksi.EntityState != EntityState.Unchanged)
                {
                    //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                    originalTP.LastUpdated = DateTime.Now;
                }
            }
            //clearing
            foreach (int removedId in originalTPs)
            {
                context.TransaksiProduk.DeleteObject(
                    originalTransaksi.TransaksiProduk.First(
                    tp => tp.IdTransaksiProduk == removedId));
            }

            //originalTransaksi.TransaksiPembayaran.Clear();
            TransaksiPembayaran originalTB = null;
            foreach (TransaksiPembayaran updatedTB in updatedTransaksi.TransaksiPembayaran)
            {
                if (originalTBs.Remove(updatedTB.IdTransaksiPembayaran))
                {
                    originalTB = originalTransaksi.TransaksiPembayaran.First(
                        tb => tb.IdTransaksiPembayaran == updatedTB.IdTransaksiPembayaran);
                }
                else
                {
                    originalTB = context.TransaksiPembayaran.CreateObject();
                    context.TransaksiPembayaran.AddObject(originalTB);
                    originalTransaksi.TransaksiPembayaran.Add(originalTB);
                    originalTransaksi.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
                }
                //originalTB.IdTransaksiPembayaran = updatedTB.IdTransaksiPembayaran;
                //originalTB.IdTransaksi = updatedTB.IdTransaksi;
                originalTB.IdJenisPembayaran = updatedTB.IdJenisPembayaran;
                originalTB.NominalPembayaran = updatedTB.NominalPembayaran;

                if (originalTransaksi.EntityState != EntityState.Unchanged)
                {
                    //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                    originalTB.LastUpdated = DateTime.Now;
                }
            }
            //clearing
            foreach (int removedId in originalTBs)
            {
                context.TransaksiPembayaran.DeleteObject(
                    originalTransaksi.TransaksiPembayaran.First(
                    tl => tl.IdTransaksiPembayaran == removedId));
            }
            return originalTransaksi;
        }
        */
        
        private void SynchTransaksiToTTVM(Transaksi originalT, TransaksiThumbnailViewModel ttvm)
        {
            ttvm.IdTransaksi = originalT.IdTransaksi;
            ttvm.IdKonsumen = originalT.IdKonsumen;
            ttvm.NamaKonsumen = originalT.Konsumen.Nama;
            ttvm.AlamatKonsumen = originalT.Konsumen.Alamat;
            ttvm.TeleponKonsumen = originalT.Konsumen.NoTelepon;
            ttvm.IdCabang = originalT.IdCabang;
            ttvm.WaktuBuat = originalT.WaktuBuat;
            ttvm.WaktuSelesai = originalT.WaktuSelesai;
            ttvm.KoreksiHarga = originalT.KoreksiHarga;
            ttvm.IsBatal = originalT.IsBatal;

            ttvm.TransaksiLayanans.Clear();
            TransaksiLayananThumbnailViewModel tltvm = null;
            foreach (var tl in originalT.TransaksiLayanan
                .OrderBy(tl => tl.IsBatal)
                .ThenBy(tl => tl.WaktuSelesai != null)
                .ThenBy(tl => tl.WaktuMulai == null)
                .ThenBy(tl => tl.WaktuTunggu == null)
                .ThenBy(tl => tl.WaktuSelesai)
                .ThenBy(tl => tl.WaktuMulai)
                .ThenBy(tl => tl.WaktuTunggu)
                .ThenBy(tl => tl.WaktuBuat))
            //foreach (var tl in (from t in originalT.TransaksiLayanan
            //                    where !t.IsBatal
            //                    orderby t.WaktuSelesai, t.WaktuMulai, t.WaktuTunggu, t.WaktuBuat
            //                    select t).ToList())
            {
                tltvm = new TransaksiLayananThumbnailViewModel();
                tltvm.IdTransaksiLayanan = tl.IdTransaksiLayanan;
                tltvm.IdTransaksi = tl.IdTransaksi;
                tltvm.NamaKonsumen = tl.Transaksi.Konsumen.Nama;
                tltvm.IdLayanan = tl.IdLayanan;
                tltvm.NamaLayanan = tl.Layanan.Nama;
                tltvm.HargaLayanan = tl.HargaLayanan;
                tltvm.IdKaryawan = tl.IdKaryawan;
                tltvm.NamaKaryawan = tl.Karyawan.Nama;
                tltvm.NamaPromo = tl.NamaPromo;
                tltvm.PotonganPromo = tl.PotonganPromo;
                tltvm.NamaFreeGift = tl.NamaFreeGift;
                tltvm.IdJenisStok = tl.IdJenisStok;
                if (tl.IdJenisStok.HasValue)
                {
                    tltvm.NamaJenisStok = tl.JenisStok.Nama;
                }
                tltvm.JumlahFreeGift = tl.JumlahFreeGift;
                tltvm.NilaiKepuasan = tl.NilaiKepuasan;
                tltvm.WaktuBuat = tl.WaktuBuat;
                tltvm.WaktuTunggu = tl.WaktuTunggu;
                tltvm.WaktuMulai = tl.WaktuMulai;
                tltvm.WaktuSelesai = tl.WaktuSelesai;
                tltvm.IsBatal = tl.IsBatal;
                tltvm.PreviousStatusTransaksiLayanan = tltvm.StatusTransaksiLayanan;
                ttvm.TransaksiLayanans.Add(tltvm);
            }

            ttvm.TransaksiProduks.Clear();
            TransaksiProdukThumbnailViewModel tptvm = null;
            foreach (var tp in originalT.TransaksiProduk
                .OrderBy(tp => tp.IsBatal))
            {
                tptvm = new TransaksiProdukThumbnailViewModel();
                tptvm.IdTransaksiProduk = tp.IdTransaksiProduk;
                tptvm.IdTransaksi = tp.IdTransaksi;
                tptvm.IdJenisStok = tp.IdJenisStok;
                tptvm.NamaJenisStok = tp.JenisStok.Nama;
                tptvm.IdKaryawan = tp.IdKaryawan;
                tptvm.NamaKaryawan = tp.Karyawan.Nama;
                tptvm.JumlahProduk = tp.JumlahProduk;
                tptvm.HargaProduk = tp.HargaProduk;
                tptvm.PotonganHarga = tp.PotonganHarga;
                tptvm.IsBatal = tp.IsBatal;
                tptvm.WaktuBatal = tp.WaktuBatal;
                //tptvm.PreviousStatusTransaksiProduk = tptvm.StatusTransaksiProduk;
                ttvm.TransaksiProduks.Add(tptvm);
            }

            ttvm.TransaksiPembayarans.Clear();
            TransaksiPembayaranThumbnailViewModel tbtvm = null;
            foreach (var tb in originalT.TransaksiPembayaran)
            {
                tbtvm = new TransaksiPembayaranThumbnailViewModel();
                tbtvm.IdTransaksiPembayaran = tb.IdTransaksiPembayaran;
                tbtvm.IdTransaksi = tb.IdTransaksi;
                tbtvm.IdJenisPembayaran = tb.IdJenisPembayaran;
                tbtvm.NamaJenisPembayaran = tb.JenisPembayaran.Nama;
                tbtvm.NominalPembayaran = tb.NominalPembayaran;
                ttvm.TransaksiPembayarans.Add(tbtvm);
            }
        }
        private void SynchTransaksiToTVM(Transaksi originalT, TransaksiViewModel tvm)
        {
            tvm.IdTransaksi.DataValue = originalT.IdTransaksi;
            tvm.IdKonsumen.DataValue = originalT.IdKonsumen;
            tvm.NamaKonsumen = originalT.Konsumen.Nama;
            tvm.AlamatKonsumen = originalT.Konsumen.Alamat;
            tvm.TeleponKonsumen = originalT.Konsumen.NoTelepon;
            tvm.IdCabang.DataValue = originalT.IdCabang;
            tvm.WaktuBuat.DataValue = originalT.WaktuBuat;
            tvm.WaktuSelesai.DataValue = originalT.WaktuSelesai;
            tvm.KoreksiHarga.DataValue = originalT.KoreksiHarga;
            tvm.IsBatal.DataValue = originalT.IsBatal;

            tvm.TransaksiLayanans.Clear();
            TransaksiLayananViewModel tlvm = null;
            foreach (var tl in originalT.TransaksiLayanan
                .OrderBy(tl => tl.IsBatal)
                .ThenBy(tl => tl.WaktuSelesai != null)
                .ThenBy(tl => tl.WaktuMulai == null)
                .ThenBy(tl => tl.WaktuTunggu == null)
                .ThenBy(tl => tl.WaktuSelesai)
                .ThenBy(tl => tl.WaktuMulai)
                .ThenBy(tl => tl.WaktuTunggu)
                .ThenBy(tl => tl.WaktuBuat))
            {
                tlvm = tvm.ForceCreateChildTransaksiLayananVM();
                tlvm.IdTransaksiLayanan.DataValue = tl.IdTransaksiLayanan;
                tlvm.IdTransaksi.DataValue = tl.IdTransaksi;
                tlvm.IdLayanan.DataValue = tl.IdLayanan;
                tlvm.NamaLayanan = tl.Layanan.Nama;
                tlvm.HargaLayanan = tl.HargaLayanan;
                tlvm.IdKaryawan.DataValue = tl.IdKaryawan;
                tlvm.NamaKaryawan = tl.Karyawan.Nama;
                tlvm.NamaPromo.DataValue = tl.NamaPromo;
                tlvm.PotonganPromo.DataValue = tl.PotonganPromo;
                tlvm.NamaFreeGift.DataValue = tl.NamaFreeGift;
                tlvm.IdJenisStok.DataValue = tl.IdJenisStok;
                if (tl.IdJenisStok.HasValue)
                {
                    tlvm.NamaJenisStok = tl.JenisStok.Nama;
                }
                tlvm.JumlahFreeGift.DataValue = tl.JumlahFreeGift;
                tlvm.NilaiKepuasan.DataValue = tl.NilaiKepuasan;
                tlvm.WaktuBuat.DataValue = tl.WaktuBuat;
                tlvm.WaktuTunggu.DataValue = tl.WaktuTunggu;
                tlvm.WaktuMulai.DataValue = tl.WaktuMulai;
                tlvm.WaktuSelesai.DataValue = tl.WaktuSelesai;
                tlvm.IsBatal.DataValue = tl.IsBatal;
                tlvm.PreviousStatusTransaksiLayanan = tlvm.StatusTransaksiLayanan;
                tvm.TransaksiLayanans.Add(tlvm);
            }

            tvm.TransaksiProduks.Clear();
            TransaksiProdukViewModel tpvm = null;
            foreach (var tp in originalT.TransaksiProduk
                .OrderBy(tl => tl.IsBatal))
            {
                tpvm = tvm.ForceCreateChildTransaksiProdukVM();
                tpvm.IdTransaksiProduk.DataValue = tp.IdTransaksiProduk;
                tpvm.IdTransaksi.DataValue = tp.IdTransaksi;
                tpvm.IdJenisStok.DataValue = tp.IdJenisStok;
                tpvm.NamaJenisStok= tp.JenisStok.Nama;
                tpvm.IdKaryawan.DataValue = tp.IdKaryawan;
                tpvm.NamaKaryawan = tp.Karyawan.Nama;
                tpvm.JumlahProduk.DataValue = tp.JumlahProduk;
                tpvm.HargaProduk.DataValue = tp.HargaProduk;
                tpvm.PotonganHarga.DataValue = tp.PotonganHarga;
                tpvm.IsBatal.DataValue = tp.IsBatal;
                tpvm.WaktuBatal.DataValue = tp.WaktuBatal;
                tpvm.PreviousStatusTransaksiProduk = tpvm.StatusTransaksiProduk;
                tvm.TransaksiProduks.Add(tpvm);
            }

            tvm.TransaksiPembayarans.Clear();
            TransaksiPembayaranViewModel tbvm = null;
            foreach (var tb in originalT.TransaksiPembayaran)
            {
                tbvm = tvm.ForceCreateChildTransaksiPembayaranVM();
                tbvm.IdTransaksiPembayaran.DataValue = tb.IdTransaksiPembayaran;
                tbvm.IdTransaksi.DataValue = tb.IdTransaksi;
                tbvm.IdJenisPembayaran.DataValue = tb.IdJenisPembayaran;
                tbvm.NamaJenisPembayaran = tb.JenisPembayaran.Nama;
                tbvm.NominalPembayaran.DataValue = tb.NominalPembayaran;
                tbvm.PreviousIdJenisPembayaran = tb.IdJenisPembayaran;
                tvm.TransaksiPembayarans.Add(tbvm);
            }
        }
        private void SynchTVMToTransaksi(TransaksiViewModel tvm, out Transaksi originalT, AnataEntities context)
        {
            originalT = null;
            List<int> originalTLs = new List<int>();
            List<int> originalTPs = new List<int>();
            List<int> originalTBs = new List<int>();
            if (tvm.IdTransaksi.DataValue != 0)
            {
                originalT = (from transaksi in context.Transaksi
                            where transaksi.IdTransaksi == tvm.IdTransaksi.DataValue
                            select transaksi).FirstOrDefault();
                foreach (var tl in originalT.TransaksiLayanan)
                {
                    originalTLs.Add(tl.IdTransaksiLayanan);
                }
                foreach (var tp in originalT.TransaksiProduk)
                {
                    originalTPs.Add(tp.IdTransaksiProduk);
                }
                foreach (var tb in originalT.TransaksiPembayaran)
                {
                    originalTBs.Add(tb.IdTransaksiPembayaran);
                }
            }
            else
            {
                originalT = context.Transaksi.CreateObject();
                context.Transaksi.AddObject(originalT);
                //TODO: Id Cabang & User
                originalT.IdCabang = Int32.Parse(ConfigurationManager.AppSettings["IdCabang"].ToString());
                originalT.WaktuBuat = DateTime.Now;
                //originalT.IdUser = SessionController.Instance.LoggedUserId;
                originalT.LastUpdated = DateTime.Now;
            }
            originalT.IdKonsumen = tvm.IdKonsumen.DataValue;
            originalT.WaktuSelesai = tvm.WaktuSelesai.DataValue;
            originalT.TotalHarga = tvm.TotalHarga;
            originalT.PotonganHarga = tvm.TotalPotongan;
            originalT.KoreksiHarga = tvm.KoreksiHarga.DataValue;
            originalT.IsBatal = tvm.IsBatal.DataValue;

            if (originalT.EntityState == EntityState.Modified)
            {
                //originalT.IdUser = SessionController.Instance.LoggedUserId;
                originalT.LastUpdated = DateTime.Now;
            }

            TransaksiLayanan originalTL = null;
            foreach (TransaksiLayananViewModel tlvm in tvm.TransaksiLayanans)
            {
                if (originalTLs.Remove(tlvm.IdTransaksiLayanan.DataValue))
                {
                    originalTL = originalT.TransaksiLayanan.FirstOrDefault(
                        tl => tl.IdTransaksiLayanan == tlvm.IdTransaksiLayanan.DataValue);
                }
                else
                {
                    originalTL = context.TransaksiLayanan.CreateObject();
                    context.TransaksiLayanan.AddObject(originalTL);
                    originalT.TransaksiLayanan.Add(originalTL);
                    originalTL.WaktuBuat = DateTime.Now;
                    //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                    originalTL.LastUpdated = DateTime.Now;
                }
                originalTL.IdLayanan = tlvm.IdLayanan.DataValue;
                originalTL.HargaLayanan = tlvm.HargaLayanan;
                originalTL.IdKaryawan = tlvm.IdKaryawan.DataValue;
                originalTL.NamaPromo = tlvm.NamaPromo.DataValue;
                originalTL.PotonganPromo = tlvm.PotonganPromo.DataValue;
                originalTL.NamaFreeGift = tlvm.NamaFreeGift.DataValue;
                originalTL.IdJenisStok = tlvm.IdJenisStok.DataValue;
                originalTL.JumlahFreeGift = tlvm.JumlahFreeGift.DataValue;
                originalTL.WaktuBuat = tlvm.WaktuBuat.DataValue;
                originalTL.WaktuTunggu = tlvm.WaktuTunggu.DataValue;
                originalTL.WaktuMulai = tlvm.WaktuMulai.DataValue;
                originalTL.WaktuSelesai = tlvm.WaktuSelesai.DataValue;
                originalTL.IsBatal = tlvm.IsBatal.DataValue;

                if (originalTL.EntityState == EntityState.Modified)
                {
                    //originalTL.IdUser = SessionController.Instance.LoggedUserId;
                    originalTL.LastUpdated = DateTime.Now;
                }
            }
            //clearing
            foreach (int removedId in originalTLs)
            {
                context.TransaksiLayanan.DeleteObject(
                    originalT.TransaksiLayanan.FirstOrDefault(
                        tl => tl.IdTransaksiLayanan == removedId));
            }

            TransaksiProduk originalTP = null;
            foreach (TransaksiProdukViewModel tpvm in tvm.TransaksiProduks)
            {
                if (originalTPs.Remove(tpvm.IdTransaksiProduk.DataValue))
                {
                    originalTP = originalT.TransaksiProduk.FirstOrDefault(
                        tp => tp.IdTransaksiProduk == tpvm.IdTransaksiProduk.DataValue);
                }
                else
                {
                    originalTP = context.TransaksiProduk.CreateObject();
                    context.TransaksiProduk.AddObject(originalTP);
                    originalT.TransaksiProduk.Add(originalTP);
                    //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                    originalTP.LastUpdated = DateTime.Now;
                }
                originalTP.IdJenisStok = tpvm.IdJenisStok.DataValue;
                originalTP.IdKaryawan = tpvm.IdKaryawan.DataValue;
                originalTP.JumlahProduk = tpvm.JumlahProduk.DataValue;
                originalTP.HargaProduk = tpvm.HargaProduk.DataValue;
                originalTP.PotonganHarga = tpvm.PotonganHarga.DataValue;
                originalTP.IsBatal = tpvm.IsBatal.DataValue;
                originalTP.WaktuBatal = tpvm.WaktuBatal.DataValue;

                if (originalTP.EntityState == EntityState.Modified)
                {
                    //originalTP.IdUser = SessionController.Instance.LoggedUserId;
                    originalTP.LastUpdated = DateTime.Now;
                }
            }
            //clearing
            foreach (int removedId in originalTPs)
            {
                context.TransaksiProduk.DeleteObject(
                    originalT.TransaksiProduk.FirstOrDefault(
                        tp => tp.IdTransaksiProduk == removedId));
            }

            TransaksiPembayaran originalTB = null;
            foreach (TransaksiPembayaranViewModel tbvm in tvm.TransaksiPembayarans)
            {
                if (originalTBs.Remove(tbvm.IdTransaksiPembayaran.DataValue))
                {
                    originalTB = originalT.TransaksiPembayaran.FirstOrDefault(
                        tb => tb.IdTransaksiPembayaran == tbvm.IdTransaksiPembayaran.DataValue);
                }
                else
                {
                    originalTB = context.TransaksiPembayaran.CreateObject();
                    context.TransaksiPembayaran.AddObject(originalTB);
                    originalT.TransaksiPembayaran.Add(originalTB);
                    //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                    originalTB.LastUpdated = DateTime.Now;
                }
                originalTB.IdJenisPembayaran = tbvm.IdJenisPembayaran.DataValue;
                originalTB.NominalPembayaran = tbvm.NominalPembayaran.DataValue;

                if (originalTB.EntityState == EntityState.Modified)
                {
                    //originalTB.IdUser = SessionController.Instance.LoggedUserId;
                    originalTB.LastUpdated = DateTime.Now;
                }
            }
            //clearing
            foreach (int removedId in originalTBs)
            {
                context.TransaksiPembayaran.DeleteObject(
                    originalT.TransaksiPembayaran.FirstOrDefault(
                        tl => tl.IdTransaksiPembayaran == removedId));
            }
        }
        #endregion
    }
}
